import json
import os
import re
from urllib.parse import urljoin

from config.app_config import AppConfig
from src.custom_logger import CustomLogger


class LeetCodeOperation:
    def __init__(self, requests_manager, base_url="https://leetcode.cn", **params):
        self.requests_manager = requests_manager
        self.base_url = base_url
        self.params = params.get('params')
        self.directory = AppConfig.DATA_PATH

        self.logger = CustomLogger()
        self.logger.set_log_file("leetcode_automation.log")

    def fetch_data(self, endpoint, method='GET'):
        url = urljoin(self.base_url, endpoint)
        payload = self.generate_payload() if method == 'POST' else None
        response = self.requests_manager.send_request(url, method, payload)
        response.encoding = 'utf-8'
        return self.process_response(response)

    def generate_payload(self):
        raise NotImplementedError("This method should be implemented in subclasses.")

    def process_response(self, response):
        if 'application/json' in response.headers.get('Content-Type', ''):
            return response.json()
        elif 'text/html' in response.headers.get('Content-Type', ''):
            return response.text
        else:
            raise ValueError("Unsupported Content-Type in response")

    def read_all_title_slugs(self):
        source_name = 'ProblemsetQuestionList'
        title_slugs = [slug.split(".")[0] for slug in os.listdir(os.path.join(self.directory, source_name))]
        return title_slugs
    
    def save_html(self, html_content, file_name):
        path = os.path.join(self.directory, file_name)
        with open(path, 'w', encoding='utf-8') as file:
            file.write(html_content)

    def save_json(self, data, file_name):
        path = os.path.join(self.directory, file_name)
        with open(path, 'w', encoding='utf-8') as file:
            json.dump(data, file, ensure_ascii=False, indent=4)

    def load_json(self, file_name):
        path = os.path.join(self.directory, file_name)
        with open(path, 'r', encoding='utf-8') as file:
            data = json.load(file)
        return data


    def get_slug_id_map(self, filename='question_title.json'):
        slug_id_map_file = 'slug_id_map.json'

        # Check if slug_id_map.json already exists
        if os.path.exists(slug_id_map_file):
            return self.load_json(slug_id_map_file)

        # If the file does not exist, generate and save the mapping
        questions = self.load_json(filename)
        slug_id_map = {q['titleSlug']: q['questionId'] for q in questions}
        self.save_json(slug_id_map, slug_id_map_file)

        return slug_id_map

    def get_id_slug_map(self, filename="question_title.json"):
        id_slug_map_file = 'id_slug_map.json'

        # Check if id_slug_map.json already exists
        if os.path.exists(id_slug_map_file):
            return self.load_json(id_slug_map_file)

        # If the file does not exist, generate and save the mapping
        questions = self.load_json(filename)
        id_slug_map = {q['questionId']: q['titleSlug'] for q in questions}
        self.save_json(id_slug_map, id_slug_map_file)

        return id_slug_map

    
    def get_slug_code_map(self, slug, folder_path ='DiscussTopic', code_snippets=None):
        filename = f'{slug}.json'
        discuss_topic_path = os.path.join(folder_path, filename)
        if not os.path.exists(os.path.join(self.directory, discuss_topic_path)):
            return None
        data = self.load_json(discuss_topic_path)
        discuss_code = [discuss.get("content") for discuss in data if discuss.get("content")]
        extracted_codes = []
        for snippet in code_snippets:
            lang = snippet.get("langSlug")
            code = snippet.get("code")
            pattern = re.escape(code)
            for content in discuss_code:
                match = re.search(pattern + r"[^`]+", content, re.DOTALL)
                if match:
                    typed_code = match.group()
                    extracted_codes.append((lang, typed_code))
                else:
                    pattern = r"\[\s*\]"
                    match = re.search(pattern + r"[^`]+", content, re.DOTALL)
                    if match:
                        typed_code = match.group()
                        extracted_codes.append((lang, typed_code))

        os.makedirs(os.path.join(self.directory, 'slug_code_map'), exist_ok=True)
        self.save_json(extracted_codes, os.path.join('slug_code_map', filename))
        return extracted_codes